<?php

// +----------------------------------------------------------------------
// | ShuipFCMS RBAC后台权限控制
// +----------------------------------------------------------------------
// | Copyright (c) 2012-2014 http://www.shuipfcms.com, All rights reserved.
// +----------------------------------------------------------------------
// | Author: 水平凡 <admin@abc3210.com>
// +----------------------------------------------------------------------

defined('USER_AUTH_ON') or define('USER_AUTH_ON', true); //开启权限认证
defined('NOT_AUTH_CONTROLLER') or define('NOT_AUTH_CONTROLLER', 'public'); //无需认证的控制器
defined('NOT_AUTH_ACTION') or define('NOT_AUTH_ACTION', 'public'); //无需认证的方法
defined('USER_AUTH_TYPE') or define('USER_AUTH_TYPE', 2); //认证类型 1 登录认证 2 实时认证

class RBAC {

    /**
     * 设置sessiong
     * @param type $key
     * @param type $value
     * @return type
     */
    static public function session($key, $value = '') {
        if ('' == $value) {
            //获取seesion
            return Yii::app()->session[$key];
        } else {
            //设置session
            Yii::app()->session->add($key, $value);
        }
    }

    /**
     * 当前登录下权限检查
     * @param type $map [模块/控制器/方法]，没有时，自动获取当前进行判断
     * @return boolean
     */
    static public function authenticate($map = '') {
        if (self::checkLogin() == false) {
            return false;
        }
        //是否超级管理员
        if (Yii::app()->passport->isAdministrator(false)) {
            return true;
        }
        if (!empty($map)) {
            $map = trim($map, '/');
            $map = explode('/', $map);
            if (empty($map)) {
                return false;
            }
        } else {
            $map = array(GROUP_NAME, CONTROLLER_NAME, ACTION_NAME,);
        }
        if (count($map) >= 3) {
            list($app, $controller, $action) = $map;
        } elseif (count($map) == 1) {
            $app = GROUP_NAME;
            $controller = CONTROLLER_NAME;
            $action = $map[0];
        } elseif (count($map) == 2) {
            $app = GROUP_NAME;
            list($controller, $action) = $map;
        }

        return Access::model()->isCompetence(Yii::app()->passport->roleid,$app,$controller,$action);
    }

    /**
     * 用于检测用户权限的方法,并保存到Session中，登陆成功以后，注册有权限
     * @param type $authId 用户ID
     * @return type
     */
    static function saveAccessList($authId = null) {
        if (null === $authId)
            $authId = Yii::app()->passport->isLogin();
        // 如果使用普通权限模式，保存当前用户的访问权限列表
        // 对管理员开发所有权限
/*        if (USER_AUTH_TYPE != 2 && !Yii::app()->passport->isAdministrator($authId))
            self::session("_ACCESS_LIST", RBAC::getAccessList($authId));*/
        return;
    }

    //检查当前操作是否需要认证 第二步
    static function checkAccess() {
        //如果项目要求认证，并且当前模块需要认证，则进行权限认证
        if (USER_AUTH_ON) {
            //模块
            $_controller = array();
            //动作
            $_action = array();
            //无需认证的控制器
            $_controller['no'] = explode(',', strtoupper(NOT_AUTH_CONTROLLER));
            //检查当前模块是否需要认证
            if ((!empty($_controller['no']) && !in_array(strtoupper(CONTROLLER_NAME), $_controller['no'])) || (!empty($_controller['yes']) && in_array(strtoupper(CONTROLLER_NAME), $_controller['yes']))) {
                //无需认证的操作
                $_action['no'] = explode(',', strtoupper(NOT_AUTH_ACTION));
                //检查当前操作是否需要认证
                if ((!empty($_action['no']) && !in_array(strtoupper(ACTION_NAME), $_action['no'])) || (!empty($_action['yes']) && in_array(strtoupper(ACTION_NAME), $_action['yes']))) {
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
        return false;
    }

    // 登录检查
    static public function checkLogin() {
        //检查当前操作是否需要认证
        if (RBAC::checkAccess()) {
            //检查认证识别号
            if (Yii::app()->passport->isLogin() == false) {
                return false;
            }
        }
        return true;
    }

    //权限认证的过滤器方法 第一步
    static public function AccessDecision($appName = GROUP_NAME) {
        //检查是否需要认证
        if (RBAC::checkAccess()) {
            //存在认证识别号，则进行进一步的访问决策
            $accessGuid = md5($appName . CONTROLLER_NAME . ACTION_NAME);
            //判断是否超级管理员，是无需进行权限认证
            $isSuperAdmin = Yii::app()->passport->isAdministrator();
            if (empty($isSuperAdmin)) {
                $accessList = RBAC::getAccessList(AdminBase::$uid);
                //判断是否为组件化模式，如果是，验证其全模块名
                $module = defined('P_CONTROLLER_NAME') ? P_CONTROLLER_NAME : CONTROLLER_NAME;
                if (!isset($accessList[strtoupper($appName)][strtoupper($module)][strtoupper(ACTION_NAME)])) {
                    //验证登录
                    if (self::checkLogin() == true) {
                        //做例外处理，只要有管理员帐号，都有该项权限
                        if (strtoupper($appName) == "ADMIN" && in_array(strtoupper(CONTROLLER_NAME), array("INDEX")) && in_array(strtoupper(ACTION_NAME), array("INDEX", "MAIN"))) {
                            //self::session($accessGuid, true);
                            return true;
                        }
                        //如果是public_开头的验证通过。
                        if (substr(ACTION_NAME, 0, 7) == 'public_') {
                            //self::session($accessGuid, true);
                            return true;
                        }
                    }
                    //self::session($accessGuid, false);
                    return false;
                } else {
                    //self::session($accessGuid, true);
                }
            } else {
                //超级管理员直接验证通过，且检查是否登录
                if (self::checkLogin()) {
                    return true;
                }
                return false;
            }
        }
        return true;
    }

    /**
      +----------------------------------------------------------
     * 取得当前认证号的所有权限列表
      +----------------------------------------------------------
     * @param integer $authId 用户ID
      +----------------------------------------------------------
     * @access public
      +----------------------------------------------------------
     */
    static public function getAccessList($authId) {
        //用户化信息
        $userInfo = AdminUser::model()->findByPk($authId);
        if (empty($userInfo)) {
            return false;
        }
        //角色ID
        $role_id = $userInfo->potency;
        //检查角色
        $roleinfo = Role::model()->findByPk($role_id);
        if (empty($roleinfo) || empty($roleinfo->status)) {
            return false;
        }
        //该角色全部权限
        $access = Access::model()->getAccessList($role_id);
        $accessList = array();
        foreach ($access as $acc) {
            $app = strtoupper($acc['app']);
            $controller = strtoupper($acc['controller']);
            $action = strtoupper($acc['action']);
            $accessList[$app][$controller][$action] = $action;
        }
        return $accessList;
    }

}
